package com.srs.backend.consumer;

import com.srs.backend.mapper.UserMapper;
import com.srs.backend.pojo.User;
import com.srs.backend.utils.Result;
import com.srs.backend.utils.WebSocketEncoder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.couchbase.CouchbaseProperties;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

@Component
@ServerEndpoint(value = "/websocket/{token}", encoders = { WebSocketEncoder.class})  // 注意不要以'/'结尾
public class WebSocketServer {
    //与线程安全有关的哈希表，将userID映射到相应用户的WebSocketServer
    private static ConcurrentHashMap<Integer, WebSocketServer> users = new ConcurrentHashMap<>();
    //当前链接请求的用户
    private User user;
    //后端向前端发信息,每个链接用session维护
    private Session session = null;
    private static UserMapper usersMapper;
    @Autowired
    public void setUsersMapper(UserMapper usersMapper) {
        WebSocketServer.usersMapper = usersMapper; //静态变量访问要用类名访问
    }
    @OnOpen
    public void onOpen(Session session, @PathParam("token") String token) {
        // 建立连接
        System.out.println("connected!");
        this.session = session;
        //为了方便调试，初阶段只把token当成userId看
        Integer userId = Integer.parseInt(token);
        this.user = usersMapper.selectById(userId);
        users.put(userId, this);

        System.out.println("----------");
        System.out.println(this.user.getUsername() + "建立连接!");
        // 给连接的前端发信息
        sendObject(Result.ok());
        System.out.println("----------");
    }

    @OnClose
    public void onClose() {
        // 关闭链接
        System.out.println("----------");
        System.out.println("disconnected!");
        System.out.println(this.user.getUsername() + "断开连接!");
        System.out.println("----------");

        // 断开连接的话要将user移除
        if (this.user != null) {
            users.remove((this.user.getId()));
        }
    }

    @OnMessage
    public void onMessage(String message, Session session) {
        // 从Client接收消息
        System.out.println("receive message! : " + message);
    }

    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }

    //后端向前端发信息
    public void sendMessage(String message) {
        //异步通信要加上锁
        synchronized (this.session) {
            try {
                this.session.getBasicRemote().sendText(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void sendObject(Object obj) {
        //异步通信要加上锁
        synchronized (this.session) {
            try {
                this.session.getBasicRemote().sendObject(obj);
            } catch (IOException | EncodeException e) {
                e.printStackTrace();
            }
        }
    }

    public static void sendObject(Integer id, Object obj) {
        WebSocketServer webSocketServer = users.get(id);
        synchronized (webSocketServer.session) {
            try {
                webSocketServer.session.getBasicRemote().sendObject(obj);
            } catch (IOException | EncodeException e) {
                e.printStackTrace();
            }
        }
    }

    public static void sendInfo(Integer uid, Object obj) throws IOException{
        users.forEach((id, item) -> {
            if (uid == null) {
                item.sendObject(obj);
            } else if (item.user.getId().equals(uid)) {
                item.sendObject(obj);
            }
        });
    }

    public static List<Integer> getUserIdList() {
        List<Integer> res = new LinkedList<>();
        users.forEach((id, item) -> {
            res.add(id);
        });
        return res;
    }
}
